<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
<meta name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">

    <meta name="author" content="ZhangPing">





<title>ARouter路由框架介绍 | ZhangPing&#39;s Blog</title>



    <link rel="icon" href="/favicon.ico">




    <!-- stylesheets list from _config.yml -->
    
    <link rel="stylesheet" href="/css/style.css">
    



    <!-- scripts list from _config.yml -->
    
    <script src="/js/script.js"></script>
    
    <script src="/js/tocbot.min.js"></script>
    



    
    
        
    


<meta name="generator" content="Hexo 4.2.0"></head>
<body>
    <div class="wrapper">
        <header>
    <nav class="navbar">
        <div class="container">
            <div class="navbar-header header-logo"><a href="/">ZhangPing&#39;s Blog</a></div>
            <div class="menu navbar-right">
                
                    <a class="menu-item" href="/archives">Posts</a>
                
                    <a class="menu-item" href="/category">Categories</a>
                
                    <a class="menu-item" href="/tag">Tags</a>
                
                    <a class="menu-item" href="/about">About</a>
                
                <input id="switch_default" type="checkbox" class="switch_default">
                <label for="switch_default" class="toggleBtn"></label>
            </div>
        </div>
    </nav>

    
    <nav class="navbar-mobile" id="nav-mobile">
        <div class="container">
            <div class="navbar-header">
                <div>
                    <a href="/">ZhangPing&#39;s Blog</a><a id="mobile-toggle-theme">·&nbsp;Light</a>
                </div>
                <div class="menu-toggle" onclick="mobileBtn()">&#9776; Menu</div>
            </div>
            <div class="menu" id="mobile-menu">
                
                    <a class="menu-item" href="/archives">Posts</a>
                
                    <a class="menu-item" href="/category">Categories</a>
                
                    <a class="menu-item" href="/tag">Tags</a>
                
                    <a class="menu-item" href="/about">About</a>
                
            </div>
        </div>
    </nav>

</header>
<script>
    var mobileBtn = function f() {
        var toggleMenu = document.getElementsByClassName("menu-toggle")[0];
        var mobileMenu = document.getElementById("mobile-menu");
        if(toggleMenu.classList.contains("active")){
           toggleMenu.classList.remove("active")
            mobileMenu.classList.remove("active")
        }else{
            toggleMenu.classList.add("active")
            mobileMenu.classList.add("active")
        }
    }
</script>
        <div class="main">
            <div class="container">
    
    
        <div class="post-toc">
    <div class="tocbot-list">
    </div>
    <div class="tocbot-list-menu">
        <a class="tocbot-toc-expand" onclick="expand_toc()">Expand all</a>
        <a onclick="go_top()">Back to top</a>
        <a onclick="go_bottom()">Go to bottom</a>
    </div>
</div>

<script>
    document.ready(
        function () {
            tocbot.init({
                tocSelector: '.tocbot-list',
                contentSelector: '.post-content',
                headingSelector: 'h1, h2, h3, h4, h5',
                collapseDepth: 1,
                orderedList: false,
                scrollSmooth: true,
            })
        }
    )

    function expand_toc() {
        var b = document.querySelector(".tocbot-toc-expand");
        tocbot.init({
            tocSelector: '.tocbot-list',
            contentSelector: '.post-content',
            headingSelector: 'h1, h2, h3, h4, h5',
            collapseDepth: 6,
            orderedList: false,
            scrollSmooth: true,
        });
        b.setAttribute("onclick", "collapse_toc()");
        b.innerHTML = "Collapse all"
    }

    function collapse_toc() {
        var b = document.querySelector(".tocbot-toc-expand");
        tocbot.init({
            tocSelector: '.tocbot-list',
            contentSelector: '.post-content',
            headingSelector: 'h1, h2, h3, h4, h5',
            collapseDepth: 1,
            orderedList: false,
            scrollSmooth: true,
        });
        b.setAttribute("onclick", "expand_toc()");
        b.innerHTML = "Expand all"
    }

    function go_top() {
        window.scrollTo(0, 0);
    }

    function go_bottom() {
        window.scrollTo(0, document.body.scrollHeight);
    }

</script>
    

    
    <article class="post-wrap">
        <header class="post-header">
            <h1 class="post-title">ARouter路由框架介绍</h1>
            
                <div class="post-meta">
                    
                        Author: <a itemprop="author" rel="author" href="/">ZhangPing</a>
                    

                    
                        <span class="post-time">
                        Date: <a href="#">September 20, 2017&nbsp;&nbsp;19:10:00</a>
                        </span>
                    
                    
                        <span class="post-category">
                    Category:
                            
                                <a href="/categories/Android-%E7%BB%84%E4%BB%B6/">Android-组件</a>
                            
                        </span>
                    
                </div>
            
        </header>

        <div class="post-content">
            <h3 id="一、为什么需要路由框架"><a href="#一、为什么需要路由框架" class="headerlink" title="一、为什么需要路由框架"></a>一、为什么需要路由框架</h3><p>由于最近对项目进行了组件化的设计，不同的组件之间涉及到跳转，所以产生了对路由框架的使用需求，所以选用了ARouter.</p>
<h4 id="1-原生的路由方案存在的问题"><a href="#1-原生的路由方案存在的问题" class="headerlink" title="1.原生的路由方案存在的问题"></a>1.原生的路由方案存在的问题</h4><p>(1)一般是通过显式intent和隐式intent两种方式实现的，而在显式intent的情况下，因为会存在直接的类依赖的问题，导致耦合非常严重；</p>
<p>(2)在隐式intent情况下，则会出现规则集中式管理，导致协作变得非常困难。而且一般而言配置规则都是在Manifest中的，这就导致了扩展性较差。</p>
<p>(3)使用原生的路由方案会出现跳转过程无法控制的问题，因为一旦使用了StartActivity()就无法插手其中任何环节了，只能交给系统管理，这就导致了在跳转失败的情况下无法降级，而是会直接抛出运营级的异常。</p>
<h4 id="2-为什么要用路由组件"><a href="#2-为什么要用路由组件" class="headerlink" title="2.为什么要用路由组件"></a>2.为什么要用路由组件</h4><p>使用自定义的路由组件就可以解决以上的一些问题，比如通过URL索引就可以解决类依赖的问题；通过分布式管理页面配置可以解决隐式intent中集中式管理Path的问题；自己实现整个路由过程也可以拥有良好的扩展性，还可以通过AOP的方式解决跳转过程无法控制的问题，与此同时也能够提供非常灵活的降级方式。还会涉及到其他的两个大方面：一方面是组件化，而另一方面就是Native和H5的问题。</p>
<p>(1)组件化的问题：一旦一款APP达到一定体量的时候，业务就会膨胀得比较严重，而开发团队的规模也会越来越大，这时候一般都会提出组件化的概念。组件化就是将APP按照一定的功能和业务拆分成多个小组件，不同的组件由不同的开发小组来负责，这样就可以解决大型APP开发过程中的开发与协作的问题，将这些问题分散到小的APP中。目前而言组件化已经有非常多比较成熟的方案了，而自定义路由框架也可以非常好地解决整个APP完成组件化之后模块之间没有耦合的问题，因为没有耦合时使用原生的路由方案肯定是不可以的。</p>
<p>(2)Native与H5的问题，因为现在的APP很少是纯Native的，也很少会有纯H5的，一般情况下都是将两者进行结合。这时候就需要非常便捷并且统一的跳转方案，因为在H5中是无法使用StartActivity()跳转到Native页面的，而从Native跳转到H5页面也只能通过配置浏览器的方式实现。</p>
<p>(3)路由框架的特点</p>
<ul>
<li><p>1.分发：把一个URL或者请求按照一定的规则分配给一个服务或者页面来处理，这个流程就是分发，分发是路由框架最基本的功能，当然也可以理解成为简单的跳转。</p>
</li>
<li><p>2.管理：将组件和页面按照一定的规则管理起来，在分发的时候提供搜索、加载、修改等操作，这部分就是管理，也是路由框架的基础，上层功能都是建立在管理之上。</p>
</li>
<li><p>3.控制：就像路由器一样，路由的过程中，会有限速、屏蔽等一些控制操作，路由框架也需要在路由的过程中，对路由操作做一些定制性的扩展。</p>
</li>
</ul>
<p>(4)ARouter的优点</p>
<ul>
<li><p>1.直接解析URL路由，解析参数并赋值到对应目标字段的页面中。</p>
</li>
<li><p>2.支持多模块项目，因为现在很少有APP是单模块的项目，一般都是多模块单工程的，由不同的团队负责不同的模块开发，这时候支持多模块项目开发就显得尤为重要。</p>
</li>
<li><p>3.支持InstantRun，目前很多路由框架并不支持InstantRun，而InstantRun是Google在AndroidStudio2.0阿尔法版本中提供的新功能，其类似于代码的日更新，其只不过面向的是开发过程，这样做可以在开发的过程中减少开发和编译的次数，可以简单地将代码修改即时地同步到APK中，从而可以大规模降低开发复杂度。</p>
</li>
<li><p>4.允许自定义拦截器，ARouter是支持拦截器的，而拦截器其实就是AOP的实现。</p>
</li>
<li><p>5.ARouter可以提供IOC容器，IOC其实就是控制反转，并通过依赖注入实现。</p>
</li>
<li><p>6.映射关系自动注册，在页面不是很多的小型APP上面，自动注册并不会体现出太大优势，但是对于大型APP而言，可能页面数量已经达到的几十个或者数百个，在这样的情况下，自动注册就显得非常重要了，因为不可能将每一个页面都通过代码的方式进行注册。</p>
</li>
<li><p>7.灵活的降级策略，ARouter可以提供很多种降级策略供用户自行选择，而原生的路由方案存在无法灵活降级的问题，StartActivity()一旦失败将会抛出运营级异常。</p>
</li>
</ul>
<p>IOC和AOP的简单理解：<a href="http://www.jianshu.com/p/cffa033d2eae" target="_blank" rel="noopener">http://www.jianshu.com/p/cffa033d2eae</a></p>
<p>(5)典型应用场景</p>
<ul>
<li><p>1.从外部URL映射到内部页面，以及参数传递与解析</p>
</li>
<li><p>2.跨模块页面跳转，模块间解耦</p>
</li>
<li><p>3.拦截跳转过程，处理登陆、埋点等逻辑</p>
</li>
<li><p>4.跨模块API调用，模块间解耦(注册ARouter服务的形式，通过接口互相调用)</p>
</li>
</ul>
<h3 id="二、ARouter的接入说明"><a href="#二、ARouter的接入说明" class="headerlink" title="二、ARouter的接入说明"></a>二、ARouter的接入说明</h3><h4 id="1-添加依赖和配置"><a href="#1-添加依赖和配置" class="headerlink" title="1.添加依赖和配置"></a>1.添加依赖和配置</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">android &#123;</span><br><span class="line"></span><br><span class="line">    defaultConfig &#123;</span><br><span class="line"></span><br><span class="line">         ...</span><br><span class="line"></span><br><span class="line">         javaCompileOptions &#123;</span><br><span class="line"></span><br><span class="line">             annotationProcessorOptions &#123;</span><br><span class="line"></span><br><span class="line">                  arguments = [moduleName : project.getName() ]</span><br><span class="line"></span><br><span class="line">             &#125;</span><br><span class="line"></span><br><span class="line">         &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">dependencies &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 替换成最新版本, 需要注意的是api</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 要与compiler匹配使用，均使用最新版可以保证兼容</span></span><br><span class="line"></span><br><span class="line">    compile<span class="string">'com.alibaba:arouter-api:x.x.x'</span></span><br><span class="line"></span><br><span class="line">    annotationProcessor<span class="string">'com.alibaba:arouter-compiler:x.x.x'</span></span><br><span class="line"></span><br><span class="line">    ...</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="2-添加混淆规则-如果使用了Proguard"><a href="#2-添加混淆规则-如果使用了Proguard" class="headerlink" title="2.添加混淆规则(如果使用了Proguard)"></a>2.添加混淆规则(如果使用了Proguard)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">-keep publicclass com.alibaba.android.arouter.routes.**&#123;*;&#125;</span><br><span class="line"></span><br><span class="line">-keep <span class="class"><span class="keyword">class</span> *<span class="keyword">implements</span> <span class="title">com</span>.<span class="title">alibaba</span>.<span class="title">android</span>.<span class="title">arouter</span>.<span class="title">facade</span>.<span class="title">template</span>.<span class="title">ISyringe</span></span>&#123;*;&#125;</span><br></pre></td></tr></table></figure>

<h4 id="3-初始化SDK"><a href="#3-初始化SDK" class="headerlink" title="3.初始化SDK"></a>3.初始化SDK</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">ARouter.openLog();     <span class="comment">// 打印日志</span></span><br><span class="line"></span><br><span class="line">ARouter.openDebug();   <span class="comment">// 开启调试模式(如果在InstantRun模式下运行，必须开启调试模式！线上版本需要关闭,否则有安全风险)</span></span><br><span class="line"></span><br><span class="line">ARouter.printStackTrace();<span class="comment">// 打印日志的时候打印线程堆栈</span></span><br><span class="line"></span><br><span class="line">ARouter.init(<span class="keyword">this</span>);<span class="comment">// 尽可能早，推荐在Application中初始化</span></span><br></pre></td></tr></table></figure>

<h3 id="三、ARounter的基本用法"><a href="#三、ARounter的基本用法" class="headerlink" title="三、ARounter的基本用法"></a>三、ARounter的基本用法</h3><h4 id="1-添加注解"><a href="#1-添加注解" class="headerlink" title="1.添加注解"></a>1.添加注解</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 在支持路由的页面上添加注解(必选)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 这里的路径需要注意的是至少需要有两级，/xx/xx</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Route</span>(path =<span class="string">"/test/activity"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> classYourActivity extend Activity &#123;</span><br><span class="line"></span><br><span class="line">  ...</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="2-发起路由"><a href="#2-发起路由" class="headerlink" title="2.发起路由"></a>2.发起路由</h4><p>(1)应用内简单的跳转</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ARouter.getInstance()</span><br><span class="line">        .build(<span class="string">"/test/activity2"</span>)</span><br><span class="line">        .navigation();</span><br></pre></td></tr></table></figure>

<p>(2) 跳转并携带参数</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ARouter.getInstance()</span><br><span class="line">        .build(<span class="string">"/kotlin/test"</span>)</span><br><span class="line">        .withString(<span class="string">"name"</span>, <span class="string">"老王"</span>)</span><br><span class="line">        .withInt(<span class="string">"age"</span>, <span class="number">23</span>)</span><br><span class="line">        .withObject(<span class="string">"object"</span>,<span class="keyword">new</span> Object())</span><br><span class="line">        .navigation();</span><br></pre></td></tr></table></figure>

<p>(3) 旧版本转场动画跳转</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ARouter.getInstance()</span><br><span class="line">        .build(<span class="string">"/test/activity2"</span>)</span><br><span class="line">        .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)</span><br><span class="line">        .navigation(<span class="keyword">this</span>);</span><br></pre></td></tr></table></figure>

<p>(4)新版本转场动画跳转</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (Build.VERSION.SDK_INT &gt;= <span class="number">16</span>) &#123;</span><br><span class="line">    ActivityOptionsCompat compat = ActivityOptionsCompat.</span><br><span class="line">            makeScaleUpAnimation(v, v.getWidth() / <span class="number">2</span>, v.getHeight() / <span class="number">2</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    ARouter.getInstance()</span><br><span class="line">            .build(<span class="string">"/test/activity2"</span>)</span><br><span class="line">            .withOptionsCompat(compat)</span><br><span class="line">            .navigation();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>(5)带导航回调跳转</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">ARouter.getInstance()</span><br><span class="line">        .build(<span class="string">"/test/activity4"</span>)</span><br><span class="line">        .navigation(<span class="keyword">this</span>, <span class="keyword">new</span> NavCallback() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onArrival</span><span class="params">(Postcard postcard)</span> </span>&#123;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onInterrupt</span><span class="params">(Postcard postcard)</span> </span>&#123;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br></pre></td></tr></table></figure>

<p>(6)Uri跳转并携带参数</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Uri testUriMix = Uri.parse(<span class="string">"arouter://m.aliyun.com/test/activity2"</span>);</span><br><span class="line">ARouter.getInstance().build(testUriMix)</span><br><span class="line">        .withString(<span class="string">"key1"</span>, <span class="string">"value1"</span>)</span><br><span class="line">        .navigation();</span><br></pre></td></tr></table></figure>

<p>(7)通过Url跳转</p>
<p>Html的跳转链接标签</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;a href&#x3D;&quot;arouter:&#x2F;&#x2F;m.aliyun.com&#x2F;test&#x2F;activity2?key1&#x3D;value1&quot;&gt;&lt;&#x2F;a&gt;</span><br><span class="line">&lt;a href&#x3D;&quot;http:&#x2F;&#x2F;m.aliyun.com&#x2F;test&#x2F;activity1&quot;&gt;&lt;&#x2F;a&gt;</span><br></pre></td></tr></table></figure>

<p>安卓Manifest文件中注册处理Html跳转链接的SchemeFilterActivity</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&lt;activity android:name=<span class="string">".SchemeFilterActivity"</span>&gt;</span><br><span class="line">    &lt;!-- Schame --&gt;</span><br><span class="line">    &lt;intent-filter&gt;</span><br><span class="line">        &lt;data</span><br><span class="line">            android:host=<span class="string">"m.aliyun.com"</span></span><br><span class="line">            android:scheme=<span class="string">"arouter"</span>/&gt;</span><br><span class="line">        &lt;action android:name=<span class="string">"android.intent.action.VIEW"</span>/&gt;</span><br><span class="line">        &lt;category android:name=<span class="string">"android.intent.category.DEFAULT"</span>/&gt;</span><br><span class="line">        &lt;category android:name=<span class="string">"android.intent.category.BROWSABLE"</span>/&gt;</span><br><span class="line">    &lt;/intent-filter&gt;</span><br><span class="line">    &lt;!-- App Links --&gt;</span><br><span class="line">    &lt;intent-filter android:autoVerify=<span class="string">"true"</span>&gt;</span><br><span class="line">        &lt;action android:name=<span class="string">"android.intent.action.VIEW"</span>/&gt;</span><br><span class="line">        &lt;category android:name=<span class="string">"android.intent.category.DEFAULT"</span>/&gt;</span><br><span class="line">        &lt;category android:name=<span class="string">"android.intent.category.BROWSABLE"</span>/&gt;</span><br><span class="line">        &lt;data</span><br><span class="line">            android:host=<span class="string">"m.aliyun.com"</span></span><br><span class="line">            android:scheme=<span class="string">"http"</span>/&gt;</span><br><span class="line">        &lt;data</span><br><span class="line">            android:host=<span class="string">"m.aliyun.com"</span></span><br><span class="line">            android:scheme=<span class="string">"https"</span>/&gt;</span><br><span class="line">    &lt;/intent-filter&gt;</span><br><span class="line">&lt;/activity&gt;</span><br></pre></td></tr></table></figure>

<p>SchemeFilterActivity的onCreate方法中对uri进行分发</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Uri uri = getIntent().getData();</span><br><span class="line">ARouter.getInstance().build(uri).navigation(<span class="keyword">this</span>, <span class="keyword">new</span> NavCallback() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onArrival</span><span class="params">(Postcard postcard)</span> </span>&#123;</span><br><span class="line">        finish();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<h4 id="3-获取参数（IOC）"><a href="#3-获取参数（IOC）" class="headerlink" title="3.获取参数（IOC）"></a>3.获取参数（IOC）</h4><p>通过在成员变量上加@Autowired标签。ARouter路由框架会依赖注入属性值。name为传参时的Key。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span>(name = <span class="string">"boy"</span>)</span><br><span class="line"><span class="keyword">boolean</span> girl;</span><br></pre></td></tr></table></figure>

<h4 id="4-设置拦截器-AOP"><a href="#4-设置拦截器-AOP" class="headerlink" title="4.设置拦截器(AOP)"></a>4.设置拦截器(AOP)</h4><p>自定义类实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 比较经典的应用就是在跳转过程中处理登陆事件，这样就不需要在目标页重复做登陆检查</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 拦截器会在跳转之间执行，多个拦截器会按优先级顺序依次执行</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Interceptor</span>(priority = <span class="number">8</span>, name = <span class="string">"测试用拦截器"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestInterceptor</span> <span class="keyword">implements</span> <span class="title">IInterceptor</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">process</span><span class="params">(Postcard postcard, InterceptorCallback callback)</span> </span>&#123;</span><br><span class="line">   ...</span><br><span class="line">        callback.onContinue(postcard);  <span class="comment">// 处理完成，交还控制权</span></span><br><span class="line">        <span class="comment">// callback.onInterrupt(new RuntimeException("我觉得有点异常"));              // 觉得有问题，中断路由流程</span></span><br><span class="line">        <span class="comment">// 以上两种至少需要调用其中一种，否则不会继续路由</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 拦截器的初始化，会在sdk初始化的时候调用该方法，仅会调用一次</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="5-使用服务（Interface）"><a href="#5-使用服务（Interface）" class="headerlink" title="5.使用服务（Interface）"></a>5.使用服务（Interface）</h4><p>这里说到的服务不是Android四大组件中的Service，这里的服务是服务端开发的概念，就是将一部分功能和组件封装起来成为接口，以接口的形式对外提供能力，所以在这部分就可以将每个功能作为一个服务，而服务的实现就是具体的业务功能</p>
<p>(1)暴露服务</p>
<p>通过依赖注入解耦暴露服务</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 声明接口,其他组件通过接口来调用服务</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">HelloService</span> <span class="keyword">extends</span> <span class="title">IProvider</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">sayHello</span><span class="params">(String name)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><span class="comment">// 实现接口</span></span><br><span class="line"><span class="meta">@Route</span>(path = <span class="string">"/service/hello"</span>, name = <span class="string">"测试服务"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HelloServiceImpl</span> <span class="keyword">implements</span> <span class="title">HelloService</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">sayHello</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"hello, "</span> + name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>(2)发现服务</p>
<p>通过依赖查找发现服务：主动去发现服务并使用。ARouter发现服务主要有两种方式，ByName和ByType。先看看这两种方式分别是怎么使用。ByName就是需要传递path路径来进行发现，ByType就是通过服务class来进行查找。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">case</span> R.id.navByName:</span><br><span class="line"> ((HelloService)ARouter.getInstance().build(<span class="string">"/service/hello"</span>).navigation()).sayHello(<span class="string">"mike"</span>);</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> R.id.navByType:</span><br><span class="line">   ARouter.getInstance().navigation(HelloService.class).sayHello("mike");</span><br><span class="line">    <span class="keyword">break</span>;</span><br></pre></td></tr></table></figure>

<p>那么为什么需要区分两种类型？因为在Java中接口是可以有多个实现的，通过ByType的方式可能难以拿到想要的多种实现，这时候就可以通过ByName的方式获取真实想要的服务。所以其实大多数情况是通过ByType的，如果有多实现的时候就需要使用ByName。</p>
<p>(推荐)通过依赖注入发现服务：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="comment">//不设置name属性，会默认使用byType的方式发现服务(当同一接口有多个实现的时候，必须使用byName的方式发现服务)</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    HelloService helloService;</span><br><span class="line">    <span class="comment">// Autowired注解中标注name之后，将会使用byName的方式注入对应的字段</span></span><br><span class="line">    <span class="meta">@Autowired</span>(name = <span class="string">"/service/hello"</span>)</span><br><span class="line">    HelloService helloService2;</span><br><span class="line"></span><br><span class="line">    HelloService helloService3;</span><br><span class="line"></span><br><span class="line">    HelloService helloService4;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Test</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        ARouter.getInstance().inject(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testService</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        helloService.sayHello(<span class="string">"Vergil"</span>);</span><br><span class="line">        helloService2.sayHello(<span class="string">"Vergil"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="6-降级策略"><a href="#6-降级策略" class="headerlink" title="6.降级策略"></a>6.降级策略</h4><p>ARouter提供的降级策略主要有两种方式，一种是通过回调的方式；一种是提供服务接口的方式。我们分别来看看两种方式的使用方法：</p>
<p>(1)单独降级-回调的方式</p>
<p>这种方式在跳转失败的时候会回调NavCallback接口的onLost方法，对于降级策略主要实现感兴趣的onLost方法即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">ARouter.getInstance().build(<span class="string">"/xxx/xxx"</span>).navigation(<span class="keyword">this</span>, <span class="keyword">new</span> NavCallback() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onFound</span><span class="params">(Postcard postcard)</span> </span>&#123;</span><br><span class="line">        Log.e(<span class="string">"ARouter"</span>, <span class="string">"找到了"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onLost</span><span class="params">(Postcard postcard)</span> </span>&#123;</span><br><span class="line">        Log.e(<span class="string">"ARouter"</span>, <span class="string">"找不到了"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onArrival</span><span class="params">(Postcard postcard)</span> </span>&#123;</span><br><span class="line">        Log.e(<span class="string">"ARouter"</span>, <span class="string">"跳转完了"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onInterrupt</span><span class="params">(Postcard postcard)</span> </span>&#123;</span><br><span class="line">        Log.e(<span class="string">"ARouter"</span>, <span class="string">"被拦截了"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>(2)全局降级-服务接口的方式</p>
<p>这种方式很简单，主要处理逻辑在内部</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ARouter.getInstance().build(<span class="string">"/xxx/xxx"</span>).navigation();</span><br></pre></td></tr></table></figure>

<p>这种降级策略主要是实现服务接口DegradeService，就一个方法就是onLost，和上面的类似。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">DegradeServiceextends</span> <span class="title">IProvider</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Router has lost.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> postcard meta</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">onLost</span><span class="params">(Context context, Postcard postcard)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="7-更多功能"><a href="#7-更多功能" class="headerlink" title="7.更多功能"></a>7.更多功能</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 使用绿色通道(跳过所有的拦截器)</span></span><br><span class="line">ARouter.getInstance().build(<span class="string">"/home/main"</span>).greenChannel().navigation();</span><br><span class="line"><span class="comment">// 使用自己的日志工具打印日志</span></span><br><span class="line">ARouter.setLogger();</span><br><span class="line"><span class="comment">// 构建标准的路由请求，startActivityForResult</span></span><br><span class="line"><span class="comment">// navigation的第一个参数必须是Activity，第二个参数则是RequestCode</span></span><br><span class="line">ARouter.getInstance().build(<span class="string">"/home/main"</span>, <span class="string">"ap"</span>).navigation(<span class="keyword">this</span>, <span class="number">5</span>);</span><br><span class="line"><span class="comment">// 指定Flag</span></span><br><span class="line">ARouter.getInstance()</span><br><span class="line">        .build(<span class="string">"/home/main"</span>)</span><br><span class="line">        .withFlags()</span><br><span class="line">        .navigation();</span><br><span class="line"><span class="comment">// 获取Fragment</span></span><br><span class="line">Fragment fragment = (Fragment) ARouter.getInstance().build(<span class="string">"/test/fragment"</span>).navigation();</span><br><span class="line"><span class="comment">//获取原始的URI</span></span><br><span class="line">String uriStr = getIntent().getStringExtra(ARouter.RAW_URI);</span><br></pre></td></tr></table></figure>

<p>—————————-END—————————-</p>
<p>更详细的文档请见</p>
<p>GitHub：<a href="https://github.com/alibaba/ARouter" target="_blank" rel="noopener">https://github.com/alibaba/ARouter</a></p>

        </div>

        
            <section class="post-copyright">
                
                    <p class="copyright-item">
                        <span>Author:</span>
                        <span>ZhangPing</span>
                    </p>
                
                
                    <p class="copyright-item">
                        <span>Permalink:</span>
                        <span><a href="https://zhangpingv5.gitee.io/2017/09/20/ARouter%E8%B7%AF%E7%94%B1%E6%A1%86%E6%9E%B6%E4%BB%8B%E7%BB%8D/">https://zhangpingv5.gitee.io/2017/09/20/ARouter%E8%B7%AF%E7%94%B1%E6%A1%86%E6%9E%B6%E4%BB%8B%E7%BB%8D/</a></span>
                    </p>
                
                
                    <p class="copyright-item">
                        <span>License:</span>
                        <span>转载请注明出处</span>
                    </p>
                
                
                     <p class="copyright-item">
                         <span>Slogan:</span>
                         <span>Self-descipline grants me freedom.</span>
                     </p>
                

            </section>
        
        <section class="post-tags">
            <div>
                <span>Tag(s):</span>
                <span class="tag">
                    
                    
                        <a href="/tags/ARouter/"># ARouter</a>
                    
                        <a href="/tags/%E8%B7%AF%E7%94%B1%E6%A1%86%E6%9E%B6/"># 路由框架</a>
                    
                        
                </span>
            </div>
            <div>
                <a href="javascript:window.history.back();">back</a>
                <span>· </span>
                <a href="/">home</a>
            </div>
        </section>
        <section class="post-nav">
            
                <a class="prev" rel="prev" href="/2017/10/22/React%20Native--AppRegistry%E7%90%86%E8%A7%A3/">React Native--AppRegistry理解</a>
            
            
            <a class="next" rel="next" href="/2017/05/09/Android%E8%A7%86%E9%A2%91%E7%BC%93%E5%AD%98%E6%94%AF%E6%8C%81%E5%BA%93/">Android视频缓存实现</a>
            
        </section>


    </article>
</div>

        </div>
        <footer id="footer" class="footer">
    <div class="copyright">
        <span>© ZhangPing | Powered by <a href="https://hexo.io" target="_blank">Hexo</a> & <a href="https://github.com/Siricee/hexo-theme-Chic" target="_blank">Chic</a></span>
    </div>
</footer>

    </div>
</body>
</html>
